﻿using Naruto.Redis.Interface;
using Naruto.Redis.Config;
using Microsoft.Extensions.Options;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Naruto.Redis.Connection;

namespace Naruto.Redis.Internal
{
    public class RedisSortedSet : IRedisSortedSet
    {
        private readonly IRedisConnection redisConnection;

        private readonly RedisPrefixKey redisPrefixKey;

        /// <summary>
        /// 实例化连接
        /// </summary>
        public RedisSortedSet(IRedisConnection _redisConnection, IOptions<RedisOptions> options)
        {
            redisConnection = _redisConnection;
            //初始化key的前缀
            redisPrefixKey = options.Value.RedisPrefix ?? new RedisPrefixKey();
        }
        #region 同步
        /// <summary>
        /// SortedSet 新增
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="member"></param>
        /// <param name="score"></param>
        /// <returns></returns>
        public bool Add<T>(string key, T value, double score) => Add<T>(redisConnection.DataBase, key, value, score);
        /// <summary>
        /// 获取SortedSet的数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public List<T> GetList<T>(string key, double minScore = double.NegativeInfinity, double maxScore = double.PositiveInfinity, Order order = Order.Ascending, long skip = 0, long take = -1) => GetList<T>(redisConnection.DataBase, key, minScore, maxScore, order, skip, take);
        /// <summary>
        /// 获取集合中的数量
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public long Length(string key) => Length(redisConnection.DataBase, key);
        /// <summary>
        /// 移除SortedSet
        /// </summary>
        public bool Remove<T>(string key, T value) => Remove<T>(redisConnection.DataBase, key, value);

        /// <summary>
        /// 根据排序的值删除数据
        /// </summary>
        /// <param name="minScore">最小的排序值</param>
        /// <param name="maxScore">最大的排序值</param>
        /// <returns></returns>
        public long RemoveByScore(string key, double minScore, double maxScore)
        {
            return RemoveByScore(redisConnection.DataBase, key, minScore, maxScore);
        }
        #endregion

        #region 异步
        /// <summary>
        /// SortedSet 新增
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="member"></param>
        /// <param name="score"></param>
        /// <returns></returns>
        public async Task<bool> AddAsync<T>(string key, T value, double score) => await AddAsync<T>(redisConnection.DataBase, key, value, score);
        /// <summary>
        /// 获取SortedSet的数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public async Task<List<T>> GetListAsync<T>(string key, double minScore = double.NegativeInfinity, double maxScore = double.PositiveInfinity, Order order = Order.Ascending, long skip = 0, long take = -1) where T : new() => await GetListAsync<T>(redisConnection.DataBase, key, minScore, maxScore, order, skip, take);
        /// <summary>
        /// 获取集合中的数量
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<long> LengthAsync(string key) => await LengthAsync(redisConnection.DataBase, key);


        /// <summary>
        /// 移除SortedSet
        /// </summary>
        public async Task<bool> RemoveAsync<T>(string key, T value) => await RemoveAsync<T>(redisConnection.DataBase, key, value);

        /// <summary>
        /// 根据排序的值删除数据
        /// </summary>
        /// <param name="minScore">最小的排序值</param>
        /// <param name="maxScore">最大的排序值</param>
        /// <returns></returns>
        public async Task<long> RemoveByScoreAsync(string key, double minScore, double maxScore)
        {
            return await RemoveByScoreAsync(redisConnection.DataBase, key, minScore, maxScore);
        }
        #endregion

        #region database

        #region 同步
        /// <summary>
        /// SortedSet 新增
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="member"></param>
        /// <param name="score"></param>
        /// <returns></returns>
        public bool Add<T>(int dataBase, string key, T value, double score)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }
            var result = RedisBase.ConvertJson(value);
            return redisConnection.Data(dataBase).SortedSetAdd(redisPrefixKey.SortedSetKey + key, result, score);
        }
        /// <summary>
        /// 获取SortedSet的数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public List<T> GetList<T>(int dataBase, string key, double minScore = double.NegativeInfinity, double maxScore = double.PositiveInfinity, Order order = Order.Ascending, long skip = 0, long take = -1)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            var result = redisConnection.Data(dataBase).SortedSetRangeByScore(redisPrefixKey.SortedSetKey + key, minScore, maxScore, Exclude.None, order, skip, take);
            var resultList = new List<T>();
            //格式化数据
            foreach (var item in result)
            {
                resultList.Add(RedisBase.ConvertObj<T>(item.ToString()));
            }
            return resultList;
        }
        /// <summary>
        /// 获取集合中的数量
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public long Length(int dataBase, string key)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            return redisConnection.Data(dataBase).SortedSetLength(redisPrefixKey.SortedSetKey + key);
        }
        /// <summary>
        /// 移除SortedSet
        /// </summary>
        public bool Remove<T>(int dataBase, string key, T value)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }
            var result = RedisBase.ConvertJson(value);
            return redisConnection.Data(dataBase).SortedSetRemove(redisPrefixKey.SortedSetKey + key, result);
        }
        /// <summary>
        /// 根据排序的值删除数据
        /// </summary>
        /// <param name="minScore">最小的排序值</param>
        /// <param name="maxScore">最大的排序值</param>
        /// <returns></returns>
        public long RemoveByScore(int dataBase, string key, double minScore, double maxScore)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            return redisConnection.Data(dataBase).SortedSetRemoveRangeByScore(redisPrefixKey.SortedSetKey + key, minScore, maxScore);
        }
        #endregion 

        #region 异步
        /// <summary>
        /// SortedSet 新增
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="member"></param>
        /// <param name="score"></param>
        /// <returns></returns>
        public async Task<bool> AddAsync<T>(int dataBase, string key, T value, double score)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }
            var result = RedisBase.ConvertJson(value);
            return await redisConnection.Data(dataBase).SortedSetAddAsync(redisPrefixKey.SortedSetKey + key, result, score).ConfigureAwait(false);
        }
        /// <summary>
        /// 获取SortedSet的数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public async Task<List<T>> GetListAsync<T>(int dataBase, string key, double minScore = double.NegativeInfinity, double maxScore = double.PositiveInfinity, Order order = Order.Ascending, long skip = 0, long take = -1) where T : new()
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            var result = await redisConnection.Data(dataBase).SortedSetRangeByScoreAsync(redisPrefixKey.SortedSetKey + key, minScore, maxScore, Exclude.None, order, skip, take).ConfigureAwait(false);
            var resultList = new List<T>();
            //格式化数据
            foreach (var item in result)
            {
                resultList.Add(RedisBase.ConvertObj<T>(item.ToString()));
            }
            return resultList;
        }


        /// <summary>
        /// 获取集合中的数量
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<long> LengthAsync(int dataBase, string key)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            return await redisConnection.Data(dataBase).SortedSetLengthAsync(redisPrefixKey.SortedSetKey + key).ConfigureAwait(false);
        }
        /// <summary>
        /// 移除SortedSet
        /// </summary>
        public async Task<bool> RemoveAsync<T>(int dataBase, string key, T value)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }
            var result = RedisBase.ConvertJson(value);
            return await redisConnection.Data(dataBase).SortedSetRemoveAsync(redisPrefixKey.SortedSetKey + key, result).ConfigureAwait(false);
        }
        /// <summary>
        /// 根据排序的值删除数据
        /// </summary>
        /// <param name="minScore">最小的排序值</param>
        /// <param name="maxScore">最大的排序值</param>
        /// <returns></returns>
        public async Task<long> RemoveByScoreAsync(int dataBase, string key, double minScore, double maxScore)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            return await redisConnection.Data(dataBase).SortedSetRemoveRangeByScoreAsync(redisPrefixKey.SortedSetKey + key, minScore, maxScore).ConfigureAwait(false);
        }
        #endregion

        #endregion
    }
}
